package fr.utbm.VI51.lemmings_world_editor;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.Scanner;
import java.util.StringTokenizer;

import javax.imageio.ImageIO;
import javax.imageio.stream.FileImageOutputStream;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;


/**
 * @author Adrien
 * 
 * This is The principal Frame of the application
 *
 */
public class MainWindowFrame extends JFrame implements MouseListener, ButtonListener, MouseMotionListener{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private MapPanel mapView;
	private BrushSelectorPanel brushSelectorView;
	private ButtonPanel buttonPanel;
	private BrushSizePanel brushSizePanel;
	private JMenuBar menu;
	
	/**
	 * Constructor of the main window frame
	 */
	public MainWindowFrame(){
		super("World level editor - VI51 - Lemmings project"); //$NON-NLS-1$
		
		setLocationRelativeTo(null);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		// Create the main Panel
		setLayout(null);
		setResizable(false);
		setBounds(0, 0, Settings.GUI_WINDOWS_WIDTH, Settings.GUI_WINDOWS_HEIGHT);
		
		// Input dialog: resolution and number of cases
		MapConfigDialog mapConfigDialog = new MapConfigDialog(this, "Map properties", true); //$NON-NLS-1$
		
		int height 			= mapConfigDialog.getMapConfig().getHeight();
		int width 			= mapConfigDialog.getMapConfig().getWidth();
		int pixelsPerCase 	= mapConfigDialog.getMapConfig().getPixelsPerCase();
		
		//Release resources
		mapConfigDialog.dispose();
		
		// Create the Map Panel
		this.mapView = new MapPanel(height, width, pixelsPerCase);
		this.mapView.setBounds(10, 85, width * pixelsPerCase, height * pixelsPerCase);
		this.mapView.setBackground(Color.WHITE);
		add(this.mapView);
		this.mapView.addMouseListener(this);
		this.mapView.addMouseMotionListener(this);
		
		// Brush selector panel
		this.brushSelectorView = new BrushSelectorPanel(new String("Brush selector")); //$NON-NLS-1$
		this.brushSelectorView.setBounds(10, 0, 500 , 80);
		add(this.brushSelectorView);
		
		// Brush size panel
		this.brushSizePanel = new BrushSizePanel(new String("Brush Size")); //$NON-NLS-1$
		this.brushSizePanel.setBounds(520, 0, 250, 80);
		add(this.brushSizePanel);
		
		// Buttons panel
		this.buttonPanel = new ButtonPanel("Actions"); //$NON-NLS-1$
		this.buttonPanel.setBounds(780, 0, 250, 80);
		this.buttonPanel.addButtonListener(this);
		add(this.buttonPanel);
		
		createTopMenu();
		
		setVisible(true);
		requestFocus();
		
		this.mapView.repaint();		
	}
	
	/**
	 * Create the top menu of the window
	 */
	private void createTopMenu() {
		this.menu = new JMenuBar();
		JMenu help = new JMenu("?"); //$NON-NLS-1$
		JMenuItem about = new JMenuItem("About"); //$NON-NLS-1$

		about.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e){
				JOptionPane.showMessageDialog(MainWindowFrame.this, "World level editor - VI51 project - Tarik Belabbas & Adrien Hoffer & Vincent Perradin & Guillaume Vinson\n", "About",JOptionPane.NO_OPTION); //$NON-NLS-1$ //$NON-NLS-2$
			}
		});

		help.add(about);
		this.menu.add(help);
		this.setJMenuBar(this.menu);		
	}
	
	/* (non-Javadoc)
	 * @see ButtonListener#newMapPressed()
	 */
	@Override
	public void newMapPressed(){
		int answer = JOptionPane.showConfirmDialog(this,
				"Are you sure to want to create a new map and lose the current?"); //$NON-NLS-1$
		if(answer == 0){
			// Input dialog: resolution and number of cases
			MapConfigDialog mapConfigDialog = new MapConfigDialog(this, "Map properties", true); //$NON-NLS-1$
			
			int height 			= mapConfigDialog.getMapConfig().getHeight();
			int width 			= mapConfigDialog.getMapConfig().getWidth();
			int pixelsPerCases 	= mapConfigDialog.getMapConfig().getPixelsPerCase();
			
			//Release resources
			mapConfigDialog.dispose();
			
			// Create the Map Panel
			this.mapView.changeMapConfig(height, width, pixelsPerCases);
			this.mapView.setBounds(10, 85, width * pixelsPerCases, height * pixelsPerCases);
			
			//Draw the map on the screen
			this.mapView.repaint();
		}
	}
	
	/* (non-Javadoc)
	 * @see ButtonListener#savePressed()
	 */
	@Override
	public void savePressed() {
		
		//Save not allowed when the map have no exit or no entrance
		if(this.mapView.getMap().hasEntrance() && this.mapView.getMap().hasExit()){
			JFileChooser fileChooser = new JFileChooser();
			if (fileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) // Pas appuy� sur cancel
			{
				File file = fileChooser.getSelectedFile();
				PrintWriter outFlux = null;
				try
				{
					FileOutputStream outTxt = new FileOutputStream(file.getAbsolutePath()+".txt"); //$NON-NLS-1$
					//FileOutputStream out = new FileOutputStream(file.getAbsolutePath());
					
					//Save the map as a serializable object
					//ObjectOutputStream object = new ObjectOutputStream(out);
					//object.writeObject(this.mapView.getMap());
					
					//Save the map in a text file
					outFlux = new PrintWriter(outTxt);
					
					//First line: height, second: width, third : pixelsPerCases
					outFlux.println(this.mapView.getMap().getHeight());
					outFlux.println(this.mapView.getMap().getWidth());
					outFlux.println(this.mapView.getPixelsPerCases());
					
					//Next, write the elements from (0,0) to (width,height)
					for (int i = 0; i < this.mapView.getMap().getHeight(); i++) {
						for (int j = 0; j < this.mapView.getMap().getWidth(); j++) {
							outFlux.print( this.mapView.getMap().getElementAt(i, j) + " "); //$NON-NLS-1$
						}
						outFlux.println();
					}
					
					//Save the map representation in a jpeg image
					BufferedImage saveBuffer = new BufferedImage(this.mapView.getWidth(), this.mapView.getHeight(), BufferedImage.TYPE_3BYTE_BGR); 
					Graphics g = saveBuffer.getGraphics();
					this.mapView.paint(g);
					FileImageOutputStream FIOS = new FileImageOutputStream(new File(file.getAbsolutePath()+".jpg")); //$NON-NLS-1$
					ImageIO.write(saveBuffer, "JPG", FIOS); //$NON-NLS-1$ //$NON-NLS-2$
					
					outFlux.close();
					//object.close();
					//out.close();
					outTxt.close();
					g.dispose();
					FIOS.close();
				}
				catch (java.io.IOException e){
					e.printStackTrace();
				}
			}
		}
		else{
			JOptionPane.showMessageDialog(this, "The map must have an entrance and an exit to be saved!"); //$NON-NLS-1$
		}
	}

	/* (non-Javadoc)
	 * @see ButtonListener#loadPressed()
	 */
	@Override
	public void loadPressed() {
		int answer = JOptionPane.showConfirmDialog(this,
			"Are you sure to want to load a map and lose the current?"); //$NON-NLS-1$
		
		if(answer == 0){
			JFileChooser fileChooser = new JFileChooser();
			if (fileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION)
			{
				File file = fileChooser.getSelectedFile();
				
				//Beginning of the method to read the txt file:
				Scanner inFlux = null;
				try{
					FileInputStream in = new FileInputStream(file.getAbsolutePath());
					inFlux = new Scanner(in);
					String line;
					line = inFlux.nextLine();
					int height = Integer.parseInt(line);
					line = inFlux.nextLine();
					int width = Integer.parseInt(line);
					line = inFlux.nextLine();
					int pixelsPerCase = Integer.parseInt(line);
					// Create the Map Panel
					this.mapView.changeMapConfig(height, width, pixelsPerCase);
					this.mapView.setBounds(10, 85, width * pixelsPerCase, height * pixelsPerCase);
					
					StringTokenizer st = null;
					
					for (int i = 0; i < height; i++) {
						line = inFlux.nextLine();
						st = new StringTokenizer(line);
						for (int j = 0; j < width; j++) {
							this.mapView.getMap().getMap()[i][j] = Map.elements.valueOf(st.nextToken());
						}
					}
					this.mapView.getMap().setExit(true);
					this.mapView.getMap().setEntrance(true);
					//Draw the map on the screen
					this.mapView.repaint();
				}
				catch(FileNotFoundException e){
					System.out.println("fucking_error, go to bit the developper"); //$NON-NLS-1$
				}
			}
		}
	}	

	/* (non-Javadoc)
	 * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
	 */
	@Override
	public void mouseClicked(MouseEvent e) {
		this.mapView.getMap().setElements(
				this.mapView.getXInCases(e.getX()),
				this.mapView.getYInCases(e.getY()),
				this.brushSelectorView.getSelectedBrush(),
				this.brushSizePanel.getBrushSize());
		this.mapView.repaint();
	}

	@Override
	public void mouseEntered(MouseEvent arg0) {
		//		
	}

	@Override
	public void mouseExited(MouseEvent arg0) {
		//		
	}

	@Override
	public void mousePressed(MouseEvent arg0) {
		//		
	}

	@Override
	public void mouseReleased(MouseEvent arg0) {
		//		
	}

	@Override
	public void mouseDragged(MouseEvent e) {
		this.mapView.getMap().setElements(
				this.mapView.getXInCases(e.getX()),
				this.mapView.getYInCases(e.getY()),
				this.brushSelectorView.getSelectedBrush(),
				this.brushSizePanel.getBrushSize());
		this.mapView.repaint();
	}

	@Override
	public void mouseMoved(MouseEvent e) {
		//
	}
	
}
